// ContactTreeNodeBuilder.cs created with MonoDevelop
// User: draek at 10:06 A 20/11/2007
//
// To change standard headers go to Edit->Preferences->Coding->Standard Headers
//

using System;
using System.Text;
using System.Collections.Generic;

using Gtk;
using Gdk;
using GLib;

using Galaxium.Gui.GtkGui;
using Galaxium.Gui;
using Galaxium.Core;
using Galaxium.Client;

using Anculus.Core;

namespace Galaxium.Protocol.Aim.GtkGui
{
	public sealed class ContactTreeNodeBuilder : ITreeNodeBuilder<HintTreeNodeRenderer>
	{
		public string ContextMenuExtensionPoint
		{
			get { return "/Galaxium/Gui/AIM/ContactTree/ContextMenu/Contact"; }
		}
		
		public bool HasDynamicChildNodes (TreeNodeContext context)
		{
			return false;
		}

		public Type NodeType
		{
			get { return typeof (AimContact); }
		}
		
		public void RenderIcon (TreeNodeContext context, HintTreeNodeRenderer renderer, ITreeNodeWidget widget)
		{
			DefaultTreeNodeWidget nodeWidget = widget as DefaultTreeNodeWidget;
			
			if (nodeWidget != null)
			{
				CellRendererPixbuf cell = nodeWidget.GetPixbufRenderer ();
				
				if (cell != null)
				{
					AimContact contact = context.NodeObject as AimContact;
					
					ContactTreeDetailLevel detailLevel = contact.Session.Account.DetailLevel;
					
					IIconSize iconSize = IconSizes.Other;

					switch (detailLevel)
					{
						case ContactTreeDetailLevel.Compact:
							iconSize = IconSizes.Small;
							break;

						case ContactTreeDetailLevel.Normal:
							iconSize = IconSizes.Medium;
							break;

						case ContactTreeDetailLevel.Detailed:
							iconSize = IconSizes.Large;
							break;

						default:
							// not currently dealign with this size.
							break;
					}

					Pixbuf pixbuf = null;
					
					// If the detail level is compact, we dont overlay, we just display the overlay itself. 
					if (detailLevel == ContactTreeDetailLevel.Compact)
					{
						if (contact.Presence == AimPresence.Offline)
							pixbuf = IconUtility.GetIcon ("galaxium-offline", iconSize);
						else if (contact.Presence == AimPresence.Away)
							pixbuf = IconUtility.GetIcon ("galaxium-status-away", iconSize);
						else if (contact.Presence == AimPresence.Dnd)
							pixbuf = IconUtility.GetIcon ("galaxium-status-brb", iconSize);
						else if (contact.Presence == AimPresence.Na)
							pixbuf = IconUtility.GetIcon ("galaxium-status-busy", iconSize);
						else if (contact.Presence == AimPresence.Occupied)
							pixbuf = IconUtility.GetIcon ("galaxium-status-lunch", iconSize);
						else if (contact.Presence == AimPresence.Online)
							pixbuf = IconUtility.GetIcon ("galaxium-online", iconSize);
						else if (contact.Presence == AimPresence.FreeForChat)
							pixbuf = IconUtility.GetIcon ("galaxium-status-phone", iconSize);
					}
					else
					{
						if (contact.DisplayImage != null && contact.DisplayImage.ImageBuffer != null && contact.Session.Account.ShowDisplayImages && !contact.SupressImage)
						{
							try
							{
								if (contact.Presence == AimPresence.Offline)
									pixbuf = IconUtility.GetIcon ("galaxium-offline", iconSize);
								else
									pixbuf = PixbufUtility.GetFramedPixbuf (new Gdk.Pixbuf(contact.DisplayImage.ImageBuffer), detailLevel);
							}
							catch
							{
								Anculus.Core.Log.Debug ("Unable to generate an image from the data in the image buffer ["+contact.DisplayImage.ImageBuffer.Length+"] for: "+contact.UniqueIdentifier);
								if (contact.Presence == AimPresence.Offline)
									pixbuf = IconUtility.GetIcon ("galaxium-offline", iconSize);
								else
									pixbuf = IconUtility.GetIcon ("galaxium-online", iconSize);
							}
						}
						else
						{
							if (contact.Presence == AimPresence.Offline)
								pixbuf = IconUtility.GetIcon ("galaxium-offline", iconSize);
							else
								pixbuf = IconUtility.GetIcon ("galaxium-online", iconSize);
						}
						
						// We are not in compact mode, so we need to use overlays now.
						if (contact.Presence == AimPresence.Away)
							pixbuf = PixbufUtility.GetOverlayedRightPixbuf (pixbuf, IconUtility.GetIcon ("galaxium-status-away", IconSizes.Small));
						else if (contact.Presence == AimPresence.Dnd)
							pixbuf = PixbufUtility.GetOverlayedRightPixbuf (pixbuf, IconUtility.GetIcon ("galaxium-status-brb", IconSizes.Small));
						else if (contact.Presence == AimPresence.Na)
							pixbuf = PixbufUtility.GetOverlayedRightPixbuf (pixbuf, IconUtility.GetIcon ("galaxium-status-busy", IconSizes.Small));
						else if (contact.Presence == AimPresence.Occupied)
							pixbuf = PixbufUtility.GetOverlayedRightPixbuf (pixbuf, IconUtility.GetIcon ("galaxium-status-lunch", IconSizes.Small));
						else if (contact.Presence == AimPresence.FreeForChat)
							pixbuf = PixbufUtility.GetOverlayedRightPixbuf (pixbuf, IconUtility.GetIcon ("galaxium-status-phone", IconSizes.Small));
					}
					
					renderer.RenderIcon (cell, pixbuf, false);
				}
			}
		}

		public void RenderText (TreeNodeContext context, HintTreeNodeRenderer renderer, ITreeNodeWidget widget)
		{
			DefaultTreeNodeWidget nodeWidget = widget as DefaultTreeNodeWidget;
			
			if (nodeWidget != null)
			{
				ContactCellRendererText cell = (ContactCellRendererText)nodeWidget.GetTextRenderer ();
					                    
				if (cell != null)
				{
					AimContact contact = context.NodeObject as AimContact;
					IAccount account = contact.Session.Account;
					
					ContactTreeDetailLevel detailLevel = account.DetailLevel;
					bool showDisplayName = account.ShowDisplayNames;
					bool showNickname = account.ShowNicknames;
					
					StringBuilder sb = new StringBuilder ();
					
					switch (detailLevel)
					{
						case ContactTreeDetailLevel.Compact:
							// Show the identifier of this contact.
							if (showNickname)
								sb.Append (Markup.EscapeText (contact.Nickname));
							else if (showDisplayName && !contact.SupressName)
								sb.Append (Markup.EscapeText (contact.DisplayName));
						    else
								sb.Append (Markup.EscapeText (contact.UniqueIdentifier));
							
							// Show the presence status of the contact.
							sb.Append (" <span foreground=\"#505050\" weight=\"light\" size=\"small\">(<i>");
							sb.Append (contact.Presence.State);
							sb.Append ("</i>)</span>");
							break;

						case ContactTreeDetailLevel.Normal:
							// Show the identifier of this contact.
							if (showNickname)
								sb.Append (Markup.EscapeText (contact.Nickname));
							else if (showDisplayName && !contact.SupressName)
								sb.Append (Markup.EscapeText (contact.DisplayName));
						    else
								sb.Append (Markup.EscapeText (contact.UniqueIdentifier));
							
							sb.Append (Environment.NewLine);

							// Show the presence and custom message of the contact.
							sb.Append ("<span foreground=\"#505050\" weight=\"light\" size=\"small\">(<i>");
							sb.Append (contact.Presence.State);
							sb.Append ("</i>) ");
							sb.Append (Markup.EscapeText (contact.DisplayMessage));
							sb.Append ("</span>");
							break;

						case ContactTreeDetailLevel.Detailed:
							// Show the identifier of this contact.
							if (showNickname)
								sb.Append (Markup.EscapeText (contact.Nickname));
							else if (showDisplayName && !contact.SupressName)
								sb.Append (Markup.EscapeText (contact.DisplayName));
						    else
								sb.Append (Markup.EscapeText ("No Name"));

							sb.Append (Environment.NewLine);

							// Show the unique identifier of this contact.
							sb.Append ("<span size=\"small\">");
							sb.Append (contact.UniqueIdentifier);
							sb.Append ("</span>");

							sb.Append (Environment.NewLine);
						
							// Show the presence and custom message of the contact.
							sb.Append ("<span foreground=\"#505050\" weight=\"light\" size=\"small\">(<i>");
							sb.Append (contact.Presence.State);
							sb.Append ("</i>) ");
							sb.Append (Markup.EscapeText (contact.DisplayMessage));
							sb.Append ("</span>");
							break;
						default:
							break;
					}

					renderer.RenderText (cell, sb.ToString (), false);
					cell.Markup = sb.ToString();
				}
			}
		}

		public void BuildDynamicChildNodes (TreeNodeContext context)
		{
		}

		public void NodeActivated (TreeNodeContext context)
		{
		}

		public string GetComparableContent (TreeNodeContext context)
		{
			AimContact contact = context.NodeObject as AimContact;
			
			return contact.Nickname;
		}
	}
}
